import urllib.parse
import requests
import time
import hmac
import hashlib
import base64


def generate_sign():
    """
    签名计算
    当你通过代码调用钉钉机器人发送消息时，请求需要携带两个参数：timestamp（时间戳）和sign（签名）。
    1、钉钉服务器收到请求后，会用你机器人的密钥、请求中的时间戳，重新计算签名。
    2、若计算结果与sign一致，且时间戳在有效期内，才会执行发送消息的操作；否则直接拒绝。
    :return:
    """
    # 当前时间戳
    timestamp = str(round(time.time() * 1000))
    # 钉钉机器人中的加签密钥
    secret = '123'

    # 将密钥转换为UTF-8编码的字节串
    secret_enc = secret.encode('utf-8')

    # 构建待签名的字符串：时间戳 + 换行符 + 密钥
    str_to_sign = '{}\n{}'.format(timestamp, secret)

    # 转为byte类型
    str_to_sign_enc = str_to_sign.encode('utf-8')

    # 使用HMAC-SHA256算法 计算签名
    #    - secret_enc: 密钥字节串
    #    - str_to_sign_enc: 待签名的字节串
    #    - digestmod=hashlib.sha256: 指定哈希算法为SHA256
    hmac_code = hmac.new(secret_enc, str_to_sign_enc, digestmod=hashlib.sha256).digest()

    # 对Base64结果进行URL编码，确保特殊字符正确传输
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))

    return timestamp, sign


def send_dd_msg(content_str, at_all=True):
    """
    向钉钉机器人推送结果
    :param content_str: 发送的内容
    :param at_all: @全员，默认为True
    :return: 
    """
    timestamp_and_sign = generate_sign()
    # url(钉钉机器人Webhook地址) + timestamp + sign

    # 构建完整的url请求，包含access_token、时间戳和签名
    url = f'https://oapi.dingtalk.com/robot/send?access_token=75d6628cefedc8225695dcde2577f03336f0099cd16d93988a68ad243cf9dd6f&timestamp={timestamp_and_sign[0]}&sign={timestamp_and_sign[1]}'
    # 设置请求头，指定JSON格式
    headers = {'Content-Type': 'application/json;charset=utf-8'}

    data = {
        "msgtype":"text", # 消息类型为文本
        "text":{
            "content":content_str # 具体消息内容
        },
        "at":{
            "isAtAll":at_all
        },
    }
    res=requests.post(url,json=data,headers=headers)
    return res.text
